<script setup>
import { ref } from "vue";
import { Plus, Upload } from "@element-plus/icons-vue";
import { useUserStore } from "@/stores";
import {
  uploadService,
  userMgrUpdateService,
  uploadDeleteFileService,
} from "@/api";
import FaceGenerator from "./FaceGenerator.vue";

// 获得用户信息存储实例
const userStore = useUserStore();
// 用于显示头像图片的URL引用
const uploadRef = ref();
// 当前用户头像图片URL
const imgUrl = ref(userStore.user.head_url);

let formData = new FormData();

/**
 * 处理文件上传事件，将文件转换为DataURL并更新imgUrl
 * @param {Object} raw 上传的文件对象 例：{name: '项目宣讲.png', lastModified: 1715759102221, lastModifiedDate: Wed May 15 2024 15:45:02 GMT+0800 (中国标准时间), webkitRelativePath: '', size: 127324, …}
 */
const onUploadFile = async ({ raw }) => {
  // 新建一个formData文件覆盖以前的格式
  let formData1 = new FormData();
  formData1.append("file", raw);
  formData = formData1;

  console.log(formData.get("file"));

  //转为url预览
  imgUrl.value = URL.createObjectURL(raw);
};

/**
 * 在上传头像前进行验证
 * @param {File} rawFile 用户选择的文件
 * @returns {Boolean} 如果验证通过返回true，否则返回false
 */
const beforeAvatarUpload = (rawFile) => {
  // 打印选中的文件信息
  console.log(rawFile);
  imgFile.value = rawFile;
  // 定义允许上传的文件类型
  const allowedTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif"];
  // 检查文件类型是否被允许
  if (!allowedTypes.includes(rawFile.type)) {
    ElMessage.error("图片必须是JPG、JPEG、PNG或GIF格式");
    return false;
  } else if (rawFile.size / 1024 / 1024 > 2) {
    // 检查文件大小是否超过2MB
    ElMessage.error("图片大小不能超过2MB！");
    return false;
  }
  return true;
};

// 用于表示上传是否正在加载的引用
let loading = ref(false);

/**
 * 异步函数 onUpdateAvatar 用于更新用户头像。
 * 此函数首先上传新头像，然后删除旧头像，最后更新用户信息并刷新用户数据。
 * 无参数。
 * 无显式返回值，但会在操作成功或失败后提供消息提示。
 */

const onUpdateAvatar = async () => {
  loading.value = true; // 标记开始加载，显示加载中的状态
  try {
    // 上传服务，获取上传后的文件数据
    let { data } = await uploadService(formData);
    // 获得用户当前头像的文件名
    const objectName = userStore.user.head_url.split("/").pop();
    // 准备删除旧头像所需要的参数
    let deleteParams = {
      objectName,
    };
    // 删除旧头像
    await uploadDeleteFileService(userStore.user.id, deleteParams);
    // 准备更新用户信息的数据
    let updateData = {
      id: userStore.user.id,
      username: userStore.user.username,
      headUrl: data,
    };
    // 更新用户信息
    await userMgrUpdateService(updateData);
    // 获取更新后的用户信息
    await userStore.getUserInfo();
    // 成功消息提示
    ElMessage({ type: "success", message: "更换头像成功" });
    loading.value = false; // 结束加载状态
  } catch (error) {
    // 捕获上传过程中可能出现的错误
    console.error("上传失败", error);
    ElMessage.error("上传失败");
  } finally {
    // 无论成功或失败，最后都结束加载状态
    loading.value = false;
  }
};

/**
 * 处理预上传逻辑
 * @param {Object} data - 包含预览URL和表单数据的对象
 * @description 此函数主要用于在上传图片前，将预览URL赋值给imgUrl变量，并更新formData为传入的表单数据。
 */
const onPreUpload = (data) => {
  console.log(data); // 打印接收到的数据，用于调试
  imgUrl.value = data.previewUrl; // 将预览URL赋值给imgUrl变量
  formData = data.formData; // 更新formData为传入的表单数据
};
</script>

<template>
  <el-row style="flex-wrap: wrap">
    <el-col :span="8">
      <el-upload
        ref="uploadRef"
        class="avatar-uploader"
        :auto-upload="false"
        :show-file-list="false"
        :on-change="onUploadFile"
        :before-upload="beforeAvatarUpload"
      >
        <img v-if="imgUrl" :src="imgUrl" class="avatar" />
        <img v-else src="@/assets/avatar.jpg" width="278" />
      </el-upload>
      <br />
      <el-button
        type="primary"
        @click="uploadRef.$el.querySelector('input').click()"
        :icon="Plus"
        size="large"
      >
        选择图片
      </el-button>
      <el-button
        type="success"
        :icon="Upload"
        size="large"
        @click="onUpdateAvatar"
        :loading="loading"
      >
        上传头像
      </el-button>
    </el-col>
    <el-col :span="12">
      <FaceGenerator @preUpload="onPreUpload"></FaceGenerator>
    </el-col>
  </el-row>
</template>

<style lang="scss" scoped>
.avatar-uploader {
  :deep() {
    .avatar {
      width: 278px;
      height: 278px;
      display: block;
      object-fit: cover;
    }
    .el-upload {
      border: 1px dashed var(--el-border-color);
      border-radius: 6px;
      cursor: pointer;
      position: relative;
      overflow: hidden;
      transition: var(--el-transition-duration-fast);
    }
    .el-upload:hover {
      border-color: var(--el-color-primary);
    }
    .el-icon.avatar-uploader-icon {
      font-size: 28px;
      color: #8c939d;
      width: 278px;
      height: 278px;
      text-align: center;
    }
  }
}
</style>
